<?php

namespace app\common\model;

use Web3\Web3;
use Web3\Utils;
use Web3\Providers\HttpProvider;
use Web3\RequestManagers\HttpRequestManager;

class EthApiWeb3 extends EthApi{
	protected $web3;
	
	public function __construct($url,$timeout=60){
    $this->web3  = new Web3(new HttpProvider(new HttpRequestManager($url,$timeout)));
	}
	// 返回指定地址发生的交易数量。
	public function getTransactionCount($address){
		$cb = new Callback;
		try{
			$this->web3->eth->getTransactionCount($address,'latest',$cb);
			return Utils::toHex($cb->result,true);
		}catch(\Exception $e){
			echo 'error getTransactionCount  => ' . $e->getMessage();
			exit;
		}
	}
	public function sendRawTransaction($rawtx){
		$cb = new Callback;
		try{
			$this->web3->eth->sendRawTransaction($rawtx,$cb);
			return $cb->result;
		}catch(\Exception $e){
			echo 'error sendRawTransaction  => ' . $e->getMessage();
			exit;
		}
	}

	// 交易明细(收据)
	public function getTransactionReceipt($txid){
		$cb = new Callback;
		try{
			$this->web3->eth->getTransactionReceipt($txid,$cb);
			return $cb->result;
		}catch(\Exception $e){
			// echo 'error getTransactionReceipt  => ' . $e->getMessage();
			return false;
			exit;
		}
	}
	// 查询当前的客户端版本
	public function clientVersion(){
		$cb = new Callback;
		$this->web3->clientVersion($cb);
		return $cb->result;
	}

	// 查询以太坊网络手续费
	public function gasPrice(){
		$cb = new Callback;
		$this->web3->eth->gasPrice($cb);
		return $cb->result->toString();
		
	}
	// 查询ETH余额
	public function getBalance($address){
		$cb = new Callback();
		try{
			$this->web3->eth->getBalance($address,$cb);
			return $cb->result->toString();
		}catch(\Exception $e){
			echo 'error getBalance  => ' . $e->getMessage();
			exit;
		}

	}

	// 交易明细
	public function getTransactionByHash($hash){   
		$cb = new Callback();
		try{
			$this->web3->eth->getTransactionByHash($hash,$cb);
			return $cb->result;
		}catch(\Exception $e){
			echo 'error getTransactionByHash  => ' . $e->getMessage();
			exit;
		}
	}

	// ETH转账
	public function Transferaccounts($credential, $value, $to, $gasprice, $chainId)
    {   
		try {
			// 获取当前汽油价格
			$gasprice = $this->gasPrice();
			// 获取地址
			$walletAddress = $credential->getAddress();	
			
			// 查询地址交易数量
			$nonce = $this->getTransactionCount($walletAddress); 
			//使用RawTxBuilder生成签名的裸交易
			$rawtx = RawTxBuilder::create()          
					->credential($credential)    //绑定发起账户
					->chainId($chainId)          //设置交易提交目标链ID
					->nonce($nonce)              //设置交易nonce 
					->gasLimit('21000')          //设置交易gas上限  
					->gasPrice($gasprice)    //设置交易价格，10gwei，单位wei 
					->to($to)                    //设置交易接收账户
					->value(Utils::toWei($value, 'ether'))              //设置交易量，1kwei，单位wei 
					->getPlainTx();	             //获取裸交易码流
			//为签名交易创建一个新的消息调用交易或合约。
			//$txid 返回交易哈希	
			$txid = $this->sendRawTransaction($rawtx);
			return $txid;
			// 返回指定交易的收据，使用哈希指定交易。
			// 需要指出的是，挂起的交易其收据无效。
			// 监听交易是否完成
			$receipt = $this->waitForTransactionReceipt($txid);
			return $receipt;
		} catch (\Throwable $e) {
			echo 'error => ' . $e->getMessage();
			exit;
		}
     
	}
	

	// ETH代币转账
	public function transfer($credential, $contractaddress, $value, $to, $gasprice, $chainId)
    {   
		try {
			// 获取地址
			$walletAddress = $credential->getAddress();	
			// 
			$abi = getabi($contractaddress);
			// 查询地址交易数量
			$nonce = $this->getTransactionCount($walletAddress); 
			//使用RawTxBuilder生成签名的裸交易
			$rawtx = RawTxBuilder::create()
					->credential($credential)
					->gasLimit('60000')
					->gasPrice($gasprice)
					->chainId($chainId)
					->nonce($nonce)
					->contract($abi)  //创建合约对象
					->at($contractaddress)       //设置合约对象的部署地址
					->getSendTx('transfer',$to,$value); //获取transfer方法调用的裸交易码流
			//为签名交易创建一个新的消息调用交易或合约。
			//$txid 返回交易哈希	
			$txid = $this->sendRawTransaction($rawtx);
			// 返回指定交易的收据，使用哈希指定交易。
			// 需要指出的是，挂起的交易其收据无效。
			// 监听交易是否完成
			// $receipt = $this->waitForTransactionReceipt($txid);
			return $txid;
		} catch (\Throwable $e) {
			echo 'error => ' . $e->getMessage();
			exit;
		}
     
	}
	

	// 合约部署裸交易的生成与提交
	public function testContractDeployTx($credential,$parameter,$gasprice)
	{		
		try {
			$walletAddress = $credential->getAddress();
			$nonce = $this->getTransactionCount($walletAddress);
			$rawtx = RawTxBuilder::create()
								->credential($credential)
								->gasLimit('4000000')
								->gasPrice($gasprice)
								->chainId($parameter['chainId'])
								->nonce($nonce)
								->contract($parameter['abi'])      //创建合约对象，一个RawContract实例
								->bytecode($parameter['bin'])      //设置合约对象的字节码
								->getDeployTx(bcmul($parameter['total'],pow(10,$parameter['unit'])),$parameter['name'],$parameter['unit'],$parameter['symbol']); //获取部署裸交易码流
								// ->getDeployTx(1000000,'zhao',6,'Z'); //获取部署裸交易码流arameter['name'],$parameter['unit'],$parameter['symbol']); //获取部署裸交易码流
			$txid = $this->sendRawTransaction($rawtx);
			return $txid;
			// dump($txid);die;
			//从交易收据中获取合约部署地址并保存到文件中
			// $receipt = $this->waitForTransactionReceipt($txid);

			// return $receipt;
			// return $receipt->contractAddress;
		} catch (\Throwable $e) {
			echo 'error => ' . $e->getMessage();
			// echo 'error => ' . $e->getFile();
			exit;
		}
       
    }




	
}